#include "Management.h"
#include <QDebug>
#include <QTextStream>

Management::Management(const Car &car, const Usr &usr)
{
    this->car = car;

    this->usr = usr;

    this->EmptySpaceArr = new u_long[LotNumMax];

    /* 文件类 */
    this->File = new QFile(EmptySpaceTable);
    bool ok = this->File->open(QFile::ReadWrite);
    if (!ok) {
        qDebug() << "打开文件失败!" << endl;
        throw("打开文件失败!");
    }
    qDebug() << "打开文件ok!" << endl;

    QByteArray byteArray = File->readAll();

    /* 未读取到文件说明是第一次启动则重新初始化文件 */
    if (byteArray.isEmpty()) {
        int i = 1;
        while (i <= LotNumMax) {
            byteArray += QByteArray::number(i, 10);
            byteArray += ' ';
            i++;
        }
        this->File->write(byteArray);
    }
    this->File->close();

    int i = 0, j = 0;
    /* 数组初始化前赋空 */
    while (i < LotNumMax) {
        this->EmptySpaceArr[i++] = 0;
    }
    i = 0;
    /* 初始化数组 */
    while(j < byteArray.length()) {
        QString str;
        while (byteArray.at(j) != ' ') {
            str += byteArray.at(j);
            j++;
        }
        j++;
        if (i >= LotNumMax) {
            break;
        }
        if (!str.isEmpty()) {
            this->EmptySpaceArr[i++] = str.toInt();
            //qDebug() << EmptySpace[i - 1] << endl;
        }
    }
    qDebug() << "初始化数组ok!" << endl;

    /* sqlite数据库 */
    this->db = QSqlDatabase::addDatabase("QSQLITE");

    /* 判断是否创建成功 */
    if(!this->db.isValid()){
        qDebug() << "创建数据库失败！" << endl;
        throw("创建数据库失败！");
    }
    qDebug() << "创建数据库ok！" << endl;

    /* 给创建的数据库起名 */
    db.setDatabaseName(SQL);

    /* 打开数据库 */
    ok = db.open();
    if(!ok){
        qDebug() << "打开数据库失败！" << endl;
        throw("打开数据库失败！");
    }
    qDebug() << "打开数据库ok！" << endl;

    /* 必须要在打开数据库之后初始化数据库查询类 */
    QSqlQuery query;
    this->query = query;

    /* 创建car表结构 */
    QString cmd = "create table if not exists Car(";
    cmd += "CarNum text PRIMARY KEY,";
    cmd += "EntryTime text,";
    cmd += "LeaveTime text,";
    cmd += "ParkingTime text,";
    cmd += "Cost double,";
    cmd += "PaymentStatus text,";
    cmd += "Reservation text,";
    cmd += "ParkingNum int";
    cmd += ")";

    ok = this->query.exec(cmd);
    if(!ok){
        qDebug() << "创建车辆表失败！" << endl;
        throw("创建表车辆失败！");
    }
    qDebug() << "创建车辆表ok！" << endl;

    /* 创建Usr表结构 */
    cmd = "create table if not exists Usr(";
    cmd += "UserName text,";
    cmd += "PhoneNum text PRIMARY KEY,";
    cmd += "Password text";
    cmd += ")";

    ok = this->query.exec(cmd);
    if(!ok){
        qDebug() << "创建用户表失败！" << endl;
        throw("创建用户表失败！");
    }
    qDebug() << "创建用户表ok！" << endl;
    this->setEmptySpaceNum();

}

Management::Management()
{

    this->EmptySpaceArr = new u_long[LotNumMax];
    /* 文件类 */
    this->File = new QFile(EmptySpaceTable);
    bool ok = this->File->open(QFile::ReadWrite);
    if (!ok) {
        qDebug() << "打开文件失败!" << endl;
        throw("打开文件失败!");
    }
    qDebug() << "打开文件ok!" << endl;

    QByteArray byteArray = File->readAll();

    /* 未读取到文件说明是第一次启动则重新初始化文件 */
    if (byteArray.isEmpty()) {
        int i = 1;
        while (i <= LotNumMax) {
            byteArray += QByteArray::number(i, 10);
            byteArray += ' ';
            i++;
        }
        this->File->write(byteArray);
    }
    this->File->close();

    int i = 0, j = 0;
    /* 数组初始化前赋空 */
    while (i < LotNumMax) {
        this->EmptySpaceArr[i++] = 0;
    }
    i = 0;
    /* 初始化数组 */
    while(j < byteArray.length()) {
        QString str;
        while (byteArray.at(j) != ' ') {
            str += byteArray.at(j);
            j++;
        }
        j++;
        if (i >= LotNumMax) {
            break;
        }
        if (!str.isEmpty()) {
            this->EmptySpaceArr[i++] = str.toInt();
            //qDebug() << EmptySpace[i - 1] << endl;
        }
    }
    qDebug() << "初始化数组ok!" << endl;

    /* sqlite数据库 */
    this->db = QSqlDatabase::addDatabase("QSQLITE");

    /* 判断是否创建成功 */
    if(!this->db.isValid()){
        qDebug() << "创建数据库失败！" << endl;
        throw("创建数据库失败！");
    }
    qDebug() << "创建数据库ok！" << endl;

    /* 给创建的数据库起名 */
    db.setDatabaseName(SQL);

    /* 打开数据库 */
    ok = db.open();
    if(!ok){
        qDebug() << "打开数据库失败！" << endl;
        throw("打开数据库失败！");
    }
    qDebug() << "打开数据库ok！" << endl;

    /* 必须要在打开数据库之后初始化数据库查询类 */
    QSqlQuery query;
    this->query = query;

    /* 创建car表结构 */
    QString cmd = "create table if not exists Car(";
    cmd += "CarNum text PRIMARY KEY,";
    cmd += "EntryTime text,";
    cmd += "LeaveTime text,";
    cmd += "ParkingTime text,";
    cmd += "Cost double,";
    cmd += "PaymentStatus text,";
    cmd += "Reservation text,";
    cmd += "ParkingNum int";
    cmd += ")";

    ok = this->query.exec(cmd);
    if(!ok){
        qDebug() << "创建车辆表失败！" << endl;
        throw("创建表车辆失败！");
    }
    qDebug() << "创建车辆表ok！" << endl;

    /* 创建Usr表结构 */
    cmd = "create table if not exists Usr(";
    cmd += "UserName text,";
    cmd += "PhoneNum text PRIMARY KEY,";
    cmd += "Password text";
    cmd += ")";

    ok = this->query.exec(cmd);
    if(!ok){
        qDebug() << "创建用户表失败！" << endl;
        throw("创建用户表失败！");
    }
    qDebug() << "创建用户表ok！" << endl;
    this->setEmptySpaceNum();
}

Management::~Management()
{
    this->db.close();
    //this->File->close();
    delete this->File;
}

void Management::AddCarToDatabase()
{
    QString cmd;
    cmd.sprintf("insert into Car values ('%s', '%s', '%s', '%s', %f, '%s', '%s', %d)",
                this->car.getCarNum().toStdString().c_str(),\
                this->car.getEntryTime().toStdString().c_str(),\
                this->car.getLeaveTime().toStdString().c_str(),\
                this->car.getParkingTime().toStdString().c_str(),\
                this->car.getCost(),\
                (this->car.getPaymentStatus()?"已支付":"未支付"),\
                (this->car.getReservation()?"预约":"非预约"),\
                this->car.getParkingNum()
                );

    bool flag = this->query.exec(cmd);
    if(!flag){
        qDebug() << "插入数据Car失败！" << endl;
        throw("插入数据Car失败！");
    }
    qDebug() << "插入数据Car ok！" << endl;

}

void Management::AddCarToDatabase(Car &car)
{
    QString cmd;
    cmd.sprintf("insert into Car values ('%s', '%s', '%s', '%s', %f, '%s', '%s', %d)",
                car.getCarNum().toStdString().c_str(),\
                car.getEntryTime().toStdString().c_str(),\
                car.getLeaveTime().toStdString().c_str(),\
                car.getParkingTime().toStdString().c_str(),\
                car.getCost(),\
                (car.getPaymentStatus()?"已支付":"未支付"),\
                (car.getReservation()?"预约":"非预约"),\
                car.getParkingNum()
                );

    bool flag = this->query.exec(cmd);
    if(!flag){
        qDebug() << "插入数据Car失败！" << endl;
        throw("插入数据Car失败！");
    }
    qDebug() << "插入数据Car ok！" << endl;
}

bool Management::DeleteCarFromDatabase(const QString &CarNum)
{
    QString cmd;
    cmd.sprintf("delete from Car where CarNum = '%s'",CarNum.toStdString().c_str());
    bool flag = this->query.exec(cmd);
    if(!flag){
        qDebug() << "删除car失败！" << endl;
        return false;
    }
    qDebug() << "删除car ok！" << endl;
    return true;
}

bool Management::DeleteUsrFromDatabase(const QString &PhoneNum)
{
    QString cmd;
    cmd.sprintf("delete from Usr where PhoneNum = '%s'",PhoneNum.toStdString().c_str());
    bool flag = this->query.exec(cmd);
    if(!flag){
        qDebug() << "删除usr失败！" << endl;
        return false;
    }
    qDebug() << "删除usr ok！" << endl;
    return true;
}

void Management::AddUsrToDatabase()
{
    QString cmd;
    cmd.sprintf("insert into Usr values ('%s', '%s', '%s')",\
                this->usr.getName().toStdString().c_str(),\
                this->usr.getPhoneNum().toStdString().c_str(),\
                this->usr.getPassword().toStdString().c_str()
                );
    bool flag = this->query.exec(cmd);
    if(!flag){
        qDebug() << "插入数据Usr失败！" << endl;
        throw("插入数据Usr失败！");
    }
    qDebug() << "插入数据Usr ok！" << endl;
}

void Management::AddUsrToDatabase(Usr &usr)
{
    QString cmd;
    cmd.sprintf("insert into Usr values ('%s', '%s', '%s')",\
                usr.getName().toStdString().c_str(),\
                usr.getPhoneNum().toStdString().c_str(),\
                usr.getPassword().toStdString().c_str()
                );
    bool flag = this->query.exec(cmd);
    if(!flag){
        qDebug() << "插入数据Usr失败！" << endl;
        throw("插入数据Usr失败！");
    }
    qDebug() << "插入数据Usr ok！" << endl;
}

Car Management::QueryCarFromDatabase(const QString &CarNum, bool *ok)
{
    QString cmd;
    Car car;
    cmd.sprintf("select * from Car where CarNum = '%s'",\
                CarNum.toStdString().c_str()
                );
    bool flag = this->query.exec(cmd);
    if (!flag) {
        qDebug() << "查询车辆失败！" << endl;
        if (Q_NULLPTR != ok) {
            *ok = flag;
        }
        return car;
    }
    if (!this->query.first()) {
        flag = false;
        if (Q_NULLPTR != ok) {
            *ok = flag;
        }
        return car;
    }
    car.setCarNum(this->query.value(0).toString());
    car.setEntryTime(this->query.value(1).toString());
    car.setLeaveTime(this->query.value(2).toString());
    car.setParkingTime(this->query.value(3).toString());
    car.setCost(this->query.value(4).toDouble());

    QString str = this->query.value(5).toString();
    //qDebug() << str << endl;
    QString temp = "已支付";
    car.setPaymentStatus(str == temp ? true : false);

    str = this->query.value(6).toString();
    //qDebug() << str << endl;
    temp = "预约";
    if (flag) {
        car.setReservation(str == temp ? true : false);
    }

    car.setParkingNum(this->query.value(7).toString().toInt());

    qDebug() << "value(7):" << this->query.value(7);
    qDebug() << "ParkingNum:" << car.getParkingNum();

    this->query.clear();
    qDebug() << "查询车辆ok！" << endl;
    if (Q_NULLPTR != ok) {
        *ok = flag;

    }
    return car;
}

Usr Management::QueryUsrFromDatabase(const QString &PhoneNum, bool *ok)
{
    QString cmd;
    Usr usr;
    cmd.sprintf("select * from Usr where PhoneNum = '%s'",\
                PhoneNum.toStdString().c_str()
                );
    bool flag = this->query.exec(cmd);
    if (!flag) {
        qDebug() << "查询用户失败！" << endl;
        if (Q_NULLPTR != ok) {
            *ok = flag;
        }
        return usr;
    }
    if (!this->query.first()) {
        flag = false;
        if (Q_NULLPTR != ok) {
            *ok = flag;
        }
        return usr;
    }
    usr.setName(this->query.value(0).toString());
    usr.setPhoneNum(this->query.value(1).toString());
    usr.setPassword(this->query.value(2).toString());
    this->query.clear();
    qDebug() << "查询用户ok！" << endl;
    if (Q_NULLPTR != ok) {
        *ok = flag;
    }
    return usr;
}

u_long Management::getEmptySpace()
{
    u_long temp = this->EmptySpaceArr[0];
    if (0 == temp) {
        return temp;
    }
    int i = 0;
    for (i = 0; i < LotNumMax - 1; i++) {
        this->EmptySpaceArr[i] = this->EmptySpaceArr[i+1];
    }
    this->EmptySpaceArr[LotNumMax - 1] = 0;
    this->setEmptySpaceNum();
    this->UpdateFile();
    return temp;
}

bool Management::FreeParkingSpace(const u_long value)
{

    int i = 0;
    i = LotNumMax - 1;
    if (this->EmptySpaceArr[i]) {
        return false;
    }

    while (0 == this->EmptySpaceArr[i - 1]) {
        i--;
    }
    for (; value < this->EmptySpaceArr[i - 1] && i > 0; i--) {
        this->EmptySpaceArr[i] = this->EmptySpaceArr[i - 1];
    }
    this->EmptySpaceArr[i] = value;
    this->setEmptySpaceNum();
    //qDebug() << "-10" << endl;
    this->UpdateFile();
    return true;

}

bool Management::UpdateCarFromDatabase()
{
    bool ok = this->DeleteCarFromDatabase(this->car.getCarNum());

    if (ok) {
        this->AddCarToDatabase();
    }
    return ok;
}

bool Management::UpdateCarFromDatabase(Car &car)
{
    bool ok = this->DeleteCarFromDatabase(car.getCarNum());

    if (ok) {
        this->AddCarToDatabase(car);
    }
    return ok;
}

void Management::UpdateFile()
{

    this->File->open(QFile::WriteOnly | QFile::Truncate);

    QString str;
    int i = 0;
    while (i < LotNumMax) {
        str += QString::number((int)this->EmptySpaceArr[i], 10);
        str += ' ';
        i++;
    }
    this->File->write(str.toLatin1());
    this->File->close();
}

Car Management::getCar() const
{
    return car;
}

void Management::setCar(const Car &value)
{
    car = value;
}

Usr Management::getUsr() const
{
    return usr;
}

void Management::setUsr(const Usr &value)
{
    usr = value;
}

u_long Management::getEmptySpaceNum() const
{
    return EmptySpaceNum;
}

void Management::setEmptySpaceNum()
{
    int n = 0;
    while ( (0 != this->EmptySpaceArr[n]) && (n < LotNumMax) ) {
        n++;
    }
    this->EmptySpaceNum = n;
}
